package BitCreekTracker; /**
 * @author Ivan Litsvinenka & Emanuele Ricci
 * Classe che implementa il comportamento del Thread del Tracker che gestisce le connessioni UDP relative a un torrent
 *
 */

import BitCreekLib.Host;

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;


public class TrackerUDPThread implements Runnable {

    /**
     * Porta UDP su cui viene bindato il Tracker
     */
    private final int port;

    /**
     * Costruttore di TrackerUDPThread
     * @param port
     */
    public TrackerUDPThread ( int port ) {
        this.port = port;
    }

    /**
     * Metodo privato che aggiorna la lista dei Peer connessi e attivi per un determinato torrent
     *
     * @param torrentName Il nome del torrent
     * @param peer        Le informazioni relative al peer che ha mandato il messaggio di keep alive
     * @return True se il torrent e' presente nell'HashTable, False altrimenti.
     */
    private boolean refreshPeersList ( String torrentName, Host peer ) {
        if ( TrackerServices.tht.containsKey( torrentName ) ) {
            // New peer
            TrackerPeer temp = new TrackerPeer(peer);
            ArrayList<TrackerPeer> peerList = getPeerList(torrentName);
            boolean find = false;
            for ( TrackerPeer currentPeer : peerList ) {
                if ( temp.equals ( currentPeer ) ) {
                	currentPeer.setLastKA ();
                    find = true;
                }

            }
            if ( !find )
                TrackerServices.tht.get ( torrentName ).addPeer ( peer );
            return true;
        } else {
            return false;
        }
    }

    /* Solo DEBUG */
    private ArrayList<TrackerPeer> getPeerList( String torrentName ) {
        return TrackerServices.tht.get ( torrentName ).getPeers ();
    }

    public void run () {
        try {
            byte[] buf = new byte[1024];
            KeepAliveUdp ka;
            while ( true ) {
                DatagramSocket serverSocket = new DatagramSocket(this.port);
                // Torrent Name
                DatagramPacket keepAlivePacket = new DatagramPacket(buf, buf.length);
                serverSocket.receive(keepAlivePacket);
                ByteArrayInputStream bais =  new ByteArrayInputStream ( keepAlivePacket.getData () );
                ObjectInputStream ois = new ObjectInputStream ( bais );
                ka = ( KeepAliveUdp ) ois.readObject ();
                InetAddress touse = keepAlivePacket.getAddress ();
                if( touse.isLoopbackAddress () )
                    touse = InetAddress.getLocalHost();
                //Aggiorno keepAlive
                serverSocket.close ();
                if ( !refreshPeersList ( ka.getTorrenName (), new Host ( touse, ka.getPort ()) ) ) return;

            }
        } catch ( Exception e) {
	    	   e.printStackTrace();
        }
	}
}
